home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Tutorials / Printer / English / Drivers.doc < prev    next >
Encoding:
Text File  |  1999-10-28  |  22.1 KB  |  537 lines

  1. printer.device V44 (OS 3.5)
  2.  
  3. Drivers for the new printer.device.
  4.  
  5. The new printer.device offers many new possibilities for printer
  6. drivers and does away with some problems of the old printer.device.
  7.  
  8. Changes:
  9.  
  10. 1. The driver now always runs in a DOS process with a minimum stack
  11. size of 8 KB.
  12.  
  13. 2. The PWrite and PBothReady functions can now sensibly used in
  14. every situation, even during DoSpecial.
  15.  
  16. 3. Due to an extension of the command table, accidental exchanges of
  17. PWrite output from DoSepcial and printer.device output can be avoided.
  18.  
  19. 4. Drivers can return error messages from all necessary situations
  20. (including DoSpecial) and can use error codes of their own.
  21.  
  22. 5. Drivers are resposible for formatting and localizing their error codes.
  23.  
  24. 5. Drivers can perform color conversion, color correction, dithering etc.
  25. by themselves without having to fear side-effects with the printer.device
  26. or having to use the incovenient PDERR_TOOKCONTROL.
  27.  
  28. 6. Scaling can be done entirely by printer.device but it is also possible
  29. to request that no scaling be performed at all.
  30.  
  31. 7. Drivers can use their own structure for color. This enables the use of
  32. standard implementations for color space conversion etc.
  33.  
  34. 8. Drivers can use the new PRead function to read from the I/O interface.
  35.  
  36. 9. Drivers can influence the display of the printer preferences in order
  37. to adapt them to their interpretation of the settings.
  38.  
  39. 10. Drivers can manage their settings themselves and are allowed to have
  40. a printer dialog of their own.
  41.  
  42. 11. Drivers can return new information to applications in order to improve
  43. the printing result.
  44.  
  45.  
  46. Converting an old driver into a new driver
  47.  
  48. 1. Set driver identification
  49.  
  50. A new driver must have a version number of 44 or better and must have the
  51. PPCF_EXTENDED bit set in ped_PrinterClass. After that the PrinterExtendedData
  52. structure must be extended with the following fields:
  53.  
  54. ped_TagList is a pointer to a tag list that contains for the most part
  55. the extended driver definition.
  56.  
  57. ped_DoPreferences is a function pointer. The funtion is called in order to
  58. manage the different commands for the driver-specific settings.
  59.  
  60. ped_CallErrHook is a function pointer. The function is called in order to
  61. format driver-specific error codes and output it through a hook.
  62.  
  63. The tags of ped_TagList in full:
  64.  
  65. PRTA_8BitGuns: If the value of this tag is TRUE, every color will be computed
  66. using 256 intensities. This makes up to 16 million colors possible (although
  67. hardly any printer can print all of them). If this tag is not present or
  68. FALSE, 16 intensities per color are used, just like in previous versions
  69. of AmigaOS. New drivers should set this tag under any circumstances.
  70.  
  71. PRTA_ConvertSource: If the value of this tag is TRUE, printer.device
  72. will leave the conversion from the sRGB color space into the printer-specific
  73. color space (often YMCK) to the driver. The conversion will then be
  74. performed by calling the ped_Render function with a status of 8.
  75. The first parameter is a pointer to 24 bit BGR values (please note the
  76. unuals BGR order which is used for compatibility reasons) the
  77. second parameter contains the number of pixels in the array and the
  78. third parameter is 0 if the array is a colormap or 1 if the the array
  79. is a pixel lin. The size of each entry is given either by PRTA_ColorSize
  80. or by sizeof(union colorEntry).
  81.  
  82. PRTA_FloydDithering: If the value of this tag is TRUE, the printer.device
  83. will leave the floyd-steinberg dithering (or whatever dithering is used)
  84. to the driver. If the PRTA_8BitGuns tag is TRUE, this tag is set to TRUE
  85. implicitly, i.e. normally the driver itself is responsible for the third
  86. dither method as well.
  87.  
  88. PRTA_AntiAlias: If the value of this tag is TRUE, the printer.device will
  89. leave the smoothing to the driver. In this case the driver must perform
  90. the smoothing in the render 1 call.
  91.  
  92. PRTA_ColorCorrection: If the value of this tag is TRUE, the printer.device
  93. will leave any color correction to the driver. Due to the rudimentary nature
  94. of the built-in color correction of the printer.device it is highly reccommended
  95. to perform the color correction inside the driver - the color correction
  96. of printer.device will almost never fulfill the needs of modern printers.
  97. The color correction is performed by calling the ped_Render function
  98. with a status of 9. The first parameter is a pointer to a color array,
  99. the second parameter specifies the number of elements in the array and
  100. the third parameter is 0 for a color map or 1 for a pixel line.
  101.  
  102. PRTA_NoIO: If the value of this tag is TRUE, no I/O device will be opened.
  103. In this case the driver must not call PWrite, PBothRead or PRead. Any ouput
  104. must be performed directly by the driver. In this way fax drivers or drivers
  105. that place their ouput in a file will no longer unecessarily allocate I/O resources.
  106.  
  107. PRTA_NewColor: If the value of this tag is TRUE, printer.device will not care
  108. for the colors after conversion anymore. This tag implies that the tags
  109. PRTA_ConvertSource, PRTA_FloydDithering, PRTA_AntiAlias and
  110. PRTA_ColorCorrection all have a value of true.
  111.  
  112. PRTA_ColorSize: The value of this tag defines the size of a color or a pixel.
  113. The standard value is sizeof(union ColorEntry). With the help of this tag
  114. the driver can save more information inside a color and support more
  115. complex color spaces. If the driver doesn't have the PRTA_NewColor tag set
  116. and uses one of the printer.device algorithms for conversion, correction or
  117. anti-alias, every pixel will be interpreted as a ColorEntry union, even
  118. if a larger value is used as the total size of a pixel. Therefore in most
  119. cases it will be necessary to combine a color structure that is not identical
  120. to union ColorEntry with the PRTA_NewColor tag.
  121.  
  122. PRTA_NoScaling: If a driver wants to inhibit any scaling of the raw data
  123. by printer.device, it can do so by use of this tag. However, the scaling
  124. will still be computed, i.e. the number printer columns and lines in
  125. render case 1 will still be equal to the scaled values. The size of the
  126. raw data can be obtained from the PrtInfo.pi_width and pi_height fields.
  127. This tag automatically implies TRUE values for PRTA_FloydDithering and
  128. PRTA_AntiAlias since these algorithms can only operate on scaled data.
  129.  
  130. PRTA_DitherNames: The value of this tag is an array of 3 strings - names
  131. for the dithering methods PD_ORDERED, PD_HALFTONE and PD_FLOYD. If a
  132. driver uses dithering methods different from those it should use the tag
  133. in order to appropriately name the dither methods.
  134.  
  135. PRTA_ShadingNames: The value of this tag is an array of 4 strings - names
  136. for the shading types PS_BW, PS_GREYSCALE, PS_COLOR and PS_GREY_SCALE2.
  137. The last two strings are exchanged in their order compared to the order
  138. used in the printer preferences! If a driver uses shading methods different
  139. from the default (e.g. a special variant of grey values in the case of PS_COLOR
  140. for black/white printers), it should use the tag to appropriately name
  141. the shading methods. Please note that the PS_GREY_SCALE2 method is used
  142. internally by printer.device as a special case for the A2024 grey scale
  143. monitor, so that replacing this method does not make much sense.
  144.  
  145. PRTA_ColorCorrect: If a driver can not understand the separate setting of
  146. color correction for the red, green and blue color channels, it should set
  147. this tag to FALSE so that the checkmarks become disabled in the preferences.
  148.  
  149. PRTA_DensityInfo: Drivers that use the density settings to make further
  150. changes to the output (e.g. amount of ink) can use this tag to provide
  151. user information for every density. The value of this tag is an array of
  152. 8 string. The first string is currently ignored and must be NULL while
  153. the other 7 strings correspond to the densities 1 to 7 and are displayed
  154. accordingly by the printer preferences.
  155.  
  156. PRTA_LeftBorder, PRTA_TopBorder: Most printers have small paper margins.
  157. The left and top border on the paper onto which the printer can not print
  158. is specified in inches/1000 using these tags. The right and bottom margins
  159. are set according to the printable area. Applications can use the information
  160. on the margins and printable area to accurately place the printer output
  161. on the paper.
  162.  
  163. PRTA_MixBWColor: If an application uses segemented (striped) printing it
  164. can often significantly improve the printing speed if it prints segments
  165. that contain only black graphics/text using the black/white mode of the
  166. printer; segments with color graphics will be printed using the greyscale
  167. or color mode accordingly. However, some printers use a different ink
  168. cartrige for black/white printing than they use for color printing or
  169. they use black ink in black/white mode and mix black from yellow,
  170. cyan and magenta while in color mode. In both cases an optimization by
  171. the application is undesirable. If the value of this tag is FALSE,
  172. applications should refrain from performing such optimizations.
  173.  
  174. PRTA_Preferences: If the driver uses a driver-specific set of options and
  175. if these options options can be changed via the driver, this tag displays
  176. these circumstances with a value of TRUE. Applications will then allow
  177. access to a button labelled "Options..." which allows the user to open
  178. a window for editing the driver options. This is achieved by using the
  179. new command PRD_EDITPREFS.
  180.  
  181.  
  182. 2. Adapt algorithms
  183.  
  184. The transfer function
  185.  
  186. The Transfer() function of the driver that is responsible to transfer the
  187. pixels into the printer buffer does not need to perform scaling anymore.
  188. Up to know the special case of X-stretching was left to the drivers. This
  189. is now handled by the printer.device in all cases, the pi_ScaleX field only
  190. contains ones so the the loop for using a specific X-value an corresponding
  191. amount of times can be removed from the function.
  192.  
  193. New drivers should set the PRTA_8BitGuns tag and support printing with 256
  194. intesities per color channel. Normally this shouldn't involve much work as
  195. the typical transfer function will work just the same with 8 bits as it
  196. does with 4.
  197.  
  198. Two points have to be taken into account, though: The threshold value
  199. pi_Threshold has already been stretched to 256 intensities. Many drivers
  200. invert this value before using it, so care must be taken to perform the
  201. inversion in the correct range of values.
  202.  
  203. The dither matrices pi_dmatrix still correspond to the dither methods ordered
  204. and halftone with a grid size of 4x4. Using these matrices results in a
  205. maximum of 16 intensities per color channel in the final printout and thus
  206. results in very marginal improvements when compared to the old drivers.
  207. Instead you should use differently sized matrices depending on the print
  208. resolution, e.g. 8x8. In the case of the Floyd-Steinberg dithering algorithm
  209. the pi_dmatrix matrix will contain only averag intensities and is not
  210. suitable for dithering.
  211.  
  212. Density calculation
  213.  
  214. The SetDensity function must adjust the values of the PRTA_Leftborder,
  215. PRTA_TopBorder and PRTA_MixBWColor if these depend on the printing resolution.
  216. However, this will not apply to most printers. Applications, on the other hand,
  217. are encouraged to re-read theses values for every print density.
  218.  
  219. The render function
  220.  
  221. Two cases for the render function have been added:
  222.  
  223. Case 8: The function is called with status 8 if colors have to converted from
  224. RGB to the format of the driver. The first parameter ct contains a pointer to
  225. an array of color. Every entry has a size corresponding to the PRTA_ColorSize
  226. tag or sizeof(union ColorEntry).
  227. If you interpret the entries as a union ColorEntry the bytes with the indices
  228. PCMRED, PCMGREEN, PCMBLUE will receive the RGB values. The x parameter holds
  229. the number of entries in the array. The y parameter contains a 0 for a colormap
  230. and a 1 for a line of pixels.
  231.  
  232. The standard conversion from RGB data to YMCK (as it is used in printer.device)
  233. can look like this:
  234.  
  235. case 8:                  /* Convert RGB source to union ColorEntry */
  236. {
  237.     /*
  238.        ct       - union colorEntry *, pointer to RGB data
  239.        x        - width, number of colors in ct array
  240.        y        - 0: converting colormap, 1: converting pixel row
  241.     */
  242.     union colorEntry *ColorInt = (union colorEntry *) ct;
  243.     LONG width = x;
  244.     ULONG additive = 0xffffffff;
  245.     additive ^= (PD->pd_Preferences.PrintImage == IMAGE_NEGATIVE) ? 0xffffffff : 0;
  246.     if (PD->pd_Preferences.PrintShade == SHADE_COLOR)
  247.     {
  248.         /* we don't need PCMBLACK, so don't calculate it */
  249.         do
  250.         {
  251.             ColorInt->colorLong ^= additive;
  252.             ColorInt++;
  253.         }
  254.         while (--width);
  255.     }
  256.     else
  257.     {
  258.         /* calculate PCMBLACK */
  259.         do
  260.         {
  261.             ColorInt->colorLong ^= additive;
  262.             ColorInt->colorByte[PCMBLACK] =
  263.                 (ColorInt->colorByte[PCMYELLOW]
  264.                 + ColorInt->colorByte[PCMMAGENTA]
  265.                 + ColorInt->colorByte[PCMCYAN]) / 3;
  266.             ColorInt++;
  267.         }
  268.         while (--width);
  269.     }
  270.     break;
  271. }
  272.  
  273. Especially the calculation of the grey scale value can differ from the simple
  274. arithmetic average of the three color intensities.
  275.  
  276.  
  277. Case 9: The function is called with status 9 if colors are to be corrected.
  278. The first parameter ct contains a pointer to an array of colors in the format
  279. of the driver (after render call 8). Every entry has the size specified by
  280. the PRTA_ColorSize tag or sizeof(union ColorEntry).
  281. The x parameter contains the number of entries in the array. The y parameter
  282. is 0 for a color map and 1 for a line of pixels.
  283.  
  284. The DoSpecial function
  285.  
  286. If an entry in the command table "CommmandTable" contains "\377", the
  287. DoSpecial() function will be called. What's new: if a command contains
  288. the string "\377\377" the I/O buffers will be flushed prior to calling the
  289. function. This enables the driver to perform I/O on its own by calling PWrite,
  290. PBothReady and PRead, without any danger of the I/O becoming mixed up.
  291.  
  292. The result of the function is interpreted differently in order to enable
  293. DoSpecial to return general printer errors:
  294.  
  295. Value        Interpretation
  296.  >0           Number of characters in the buffer
  297.   0           Command not handled by DoSpecial
  298.  -1           Unsupported command
  299.  -2           (new) Command was executed but no characters were written
  300.                     to the buffer
  301. <-2           (new) An I/O or printer error minus 65536.
  302.  
  303. In order to return an error from DoSpecial you simply have to subtract
  304. 65536 from the actual error code.
  305.  
  306.  
  307. 3. Error handling
  308.  
  309. The new ped_CallErrHook field of the PrinterExtendedData structure contains
  310. a function which is called if an error code of the driver needs to formatted
  311. for output via a hook.
  312.  
  313. The driver can define error codes between PDERR_FIRSTCUSTOM and PDERR_LASTCUSTOM
  314. and return them from its functions. If the application has set a hook to output
  315. an error directly through the printer.device, the ped_CallErrHook function will
  316. be called for all error codes of the driver.
  317.  
  318. The first parameter of the function is a pointer to the I/O request that receives
  319. the error in io_Error. The second parameter is the hook that was set by the
  320. applicatioin. The driver must fill in a variable of PrtErrMsg type and then
  321. call the pd_CallErrHook function of the PrinterData structure. This will in
  322. turn contain the hook as the first parameter, the I/O request as the second
  323. parameter and a pointer to a variable of PrtErrMsg type as the third parameter.
  324. des Typs PrtErrMsg.
  325.  
  326. void ErrHook(struct IORequest *ior, struct Hook *hook)
  327. {
  328.     struct EasyStruct es;
  329.     struct PrtErrMsg pem;
  330.     LONG args[2];
  331.     es.es_StructSize = sizeof(es);
  332.     es.es_Flags = 0;
  333.     es.es_Title = NULL;
  334.     es.es_GadgetFormat = "OK";
  335.     pem.pe_Version = PDHOOK_VERSION;
  336.     pem.pe_ErrorLevel = RETURN_FAIL;
  337.     pem.pe_Window = NULL;
  338.     pem.pe_ES = &es;
  339.     pem.pe_IDCMP = NULL;
  340.     pem.pe_ArgList = NULL;
  341.     switch (ior->io_Error)
  342.     {
  343.         case FILEERR_FILEOPENFAILED:
  344.             es.es_TextFormat = "Unable to open file %s.";
  345.             args[0] = (LONG) outfile;
  346.             pem.pe_ArgList = args;
  347.             break;
  348.     }
  349.     PD->pd_CallErrHook(hook,ior,&pem);
  350. }
  351.  
  352. The es.es_Title and es.es_GadgetFormat fields may be NULL, the pd_CallErrHook
  353. will fill them appropriately before calling the hook.
  354.  
  355.  
  356. 4. Driver settings
  357.  
  358. If the driver support proprietary (driver-specific) settings it must set
  359. the PRTA_Preferences to TRUE and enter a function into ped_DoPreferences
  360. that handles the settings.
  361.  
  362. Drivers can support different concepts for settings. If the driver is likely
  363. to be used by several units it should save a separate pareferences file
  364. for each unit. If it is likely to be used by only one unit it is sufficient
  365. to use one preferences file. If the driver derives the name of the settings
  366. file from the driver name, the user will still be able to manage several
  367. sets of preferences by duplicating the driver and giving it a new name.
  368.  
  369. Another decision has to be made with regard to the size of the preferences
  370. dialog. If the driver supports a very large amount of settings it often
  371. makes sense for the driver to provide a separate preferences editor (e.g.
  372. PrinterPS) that can be used to control all settings. In this case the dialog
  373. that is opened by the PRD_EDITPREFS command should only contain that part
  374. of the settings that directly affects the printer output.
  375.  
  376. The ped_DoPreferences function is called using 2 parameters: one I/O request
  377. and one command. The command can state 7 different cases:
  378.  
  379. Case 0: set the preferences to their default values (PRD_RESETPRFS)
  380.  
  381. Case 1: load the preferences from a file (PRD_LOADPREFS)
  382.  
  383. Case 2: store the preferences in a file in ENV: (PRD_USEPREFS)
  384.  
  385. Case 3: store the preferences in a file both in ENV: and in ENVARC:
  386.         (PRD_SAVEPREFS)
  387.  
  388. Case 4: store the preferences into an I/O buffer (PRD_READPREFS)
  389.  
  390. Case 5: copy the preferences from an I/O buffer (PRD_WRITEPREFS)
  391.  
  392. Case 6: open a window in which the preferences can be changed
  393.         (PRD_EDITPREFS)
  394.  
  395.  
  396. Details of the preferences structure
  397.  
  398. A structure that is used for saving the preferences must be derived from
  399. the PrtDriverPreferences structure (Include devices/prtbase.h):
  400.  
  401. struct PrtDriverPreferences 
  402. {
  403.     UWORD    pdp_Version;       /* PRIVATE! driver specific version */
  404.     UBYTE    pdp_PrinterID[32]; /* PRIVATE! driver specific id */
  405.     char     pdp_PrefName[FILENAME_SIZE-16];
  406.     ULONG    pdp_Length; /* length of this structure */
  407.     /* more driver private fields follow*/
  408. };
  409.  
  410. By reading the version and printerID the driver can tell its settings from
  411. that of other drivers and can recognize older settings.
  412.  
  413. The PrefName array should contain a readable name for the preferences, this
  414. could e.g. be the name of the printer.
  415.  
  416. Default values
  417.  
  418. In the beginning many programs will not offer the possibility to open the
  419. preferences dialog (case 6). Therefore it is vital that the default values
  420. actually make sense and are usable.
  421.  
  422. Loading and saving of preferences
  423.  
  424. The settings of a driver will automatically be loaded when opening a unit.
  425. The file format should be an IFF FORM PREF and be structured the same way
  426. the system files are (i.e. it should contain a FORM PRHD and a separate FORM
  427. for the actual settings).
  428.  
  429. Reading and writing of preferences
  430.  
  431. An application may read the settings of the driver and store it for later
  432. reference (e.g. to save it while the unit is closed). Likewise it may
  433. write back the settings to the driver.
  434.  
  435. case 4:
  436.     /* copy preferences to ior */
  437.     sior = (struct IOStdReq *) ior;
  438.     if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(DriverPrefs))
  439.     {
  440.         CopyMem(&DriverPrefs,sior->io_Data,sizeof(DriverPrefs));
  441.         sior->io_Actual = sizeof(DriverPrefs);
  442.     }
  443.     else
  444.         error = IOERR_BADLENGTH;
  445.     break;
  446. case 5:
  447.     /* check prefs in ior and copy it to preferences */
  448.     sior = (struct IOStdReq *) ior;
  449.     if (sior->io_Data && sior->io_Offset == 0 && sior->io_Length >= sizeof(struct PrtDriverPreferences))
  450.     {
  451.         tp = (struct FileDriverPrefs *) sior->io_Data;
  452.         /* check prefs data. If this check fails 0 is returned but
  453.            io_Actual is set to 0.
  454.         */
  455.         if (checkDriverPrefs(&tp->fdp_Base))
  456.         {
  457.             CopyMem(tp,&DriverPrefs,sizeof(DriverPrefs));
  458.             sior->io_Actual = sizeof(DriverPrefs);
  459.         }
  460.         else
  461.             sior->io_Actual = 0;
  462.     }
  463.     else
  464.         error = IOERR_BADLENGTH;
  465.     break;
  466.  
  467. Damit der Treiber seine Einstellungen wiedererkennt, muß er den Kopf der
  468. Datenstruktur überprüfen:
  469.  
  470. static int
  471. checkDriverPrefs(struct PrtDriverPreferences *p)
  472. {
  473.     if (p->pdp_Version == 1
  474.         && strcmp(p->pdp_PrinterID,DriverPrefsDefault.fdp_Base.pdp_PrinterID) == 0
  475.         && p->pdp_Length == sizeof(struct FileDriverPrefs))
  476.     {
  477.         return TRUE;
  478.     }
  479.     return FALSE;
  480. }
  481.  
  482. Please note that in the case of an unrecognized structure no error will
  483. be returned but only io_Actual is set to 0. This means that the application
  484. can write back settings that were stored earlier (even in a file) - this
  485. makes a change or update of the driver "in between" possible.
  486.  
  487. Edit preferences
  488.  
  489. The I/O request for editing preferences (struct IOPrtPrefsReq) contains
  490. a tag list:
  491.  
  492. PPRA_Window: The value of this tag denotes a window. This window determines
  493. the screen to use for the preferences dialog. The window should be locked
  494. against input as long as the dialog remains opened.
  495.  
  496. PPRA_Screen: If now window was specified this tag can be used to specify
  497. a screen on which to open the preferences dialog.
  498.  
  499. PPRA_PubScreen: The name of a public screen on which to open the
  500. preferences dialog.
  501.  
  502. The only ways to leave the preferences dialog should be by way of an "OK"
  503. and a "Cancel" button, i.e. the settings will not be saved from within
  504. the dialog. The saving of the settings must be handled either by the
  505. application through PRD_READPREFS/PRD_WRITEPREFS, by a separate preferences
  506. editor or by a system application using PRD_SAVEPREFS.
  507.  
  508.  
  509. 5. Driver-specific color structure
  510.  
  511. A driver can define a color structure best suited to its needs, i.e. it
  512. need not use the standard union colorEntry structure. All printer.device
  513. needs to know is the size of the structure which is achieved by use of
  514. the PRTA_ColorSize tag. This of course means that the printer.device can
  515. only provide a very limited amount of services to the driver:
  516. Reading the bitmap and converting the data to 24 bit RGB and scaling the
  517. RGB data. All other tasks (converting from sRGB color space to the printer
  518. color space, color correction, dithering, anti-alias) must be performed
  519. by the driver.
  520.  
  521. If the driver uses a color structure that is different from union colorEntry
  522. it must set the PRTA_NewColor tag. The printer.device will then implicitly
  523. set all tags that affect the printing algorithms.
  524.  
  525. If the driver only requires some addtionals bytes in the color structure,
  526. e.g. for temporary data while dithering, it can use PRTA_ColorSize to
  527. set the size of the new color structure but leave PRTA_NewColor set to
  528. FALSE. Please note that in this case the color structure must begin with
  529. union colorEntry because this is the way the printer.device interprets
  530. the structure:
  531.  
  532. struct LargeColorEntry
  533. {
  534.     union colorEntry lce_ColorEntry;
  535.     LONG lce_Random;
  536. };
  537.